﻿#region Imports

using System;
using System.Collections.Generic;
using bGallery.Core.Data;
using bGallery.Core.Domain;
using NHibernate;
using Spring.Data.NHibernate;
using Spring.Data.NHibernate.Generic.Support;

#endregion

namespace bGallery.Data.Hibernate.Data.Hibernate
{
	/// <summary>
	/// Hibernate Category DAO
	/// </summary>
	class HibernateCategoryDao : HibernateDaoSupport, ICategoryDao
	{

		#region ICategoryDao members

		/// <summary>
		/// Loads category by id
		/// </summary>
		/// <param name="catId">Category ID</param>
		/// <returns>Loaded category</returns>
		public Category FindById(int catId)
		{
			return HibernateTemplate.Get<Category>(catId);
		}

		/// <summary>
		/// Parses string and loads category by it
		/// </summary>
		/// <param name="catId">Category ID</param>
		/// <returns>Loaded category</returns>
		public Category FindById(string catId)
		{
			return FindById(Convert.ToInt32(catId));
		}

		/// <summary>
		/// Loads category by abbreviation
		/// </summary>
		/// <param name="abbrev">Abbreviation of category</param>
		/// <returns>Loaded category</returns>
		public Category FindByAbbreviation(string abbrev)
		{
			IList<Category> cats = HibernateTemplate.Find<Category>("from Category c where c.Abbreviation = ?", abbrev);
			if (cats.Count > 0)
				return cats[0];

			return null;
		}

		/// <summary>
		/// Saves category
		/// </summary>
		/// <param name="category">Category to save</param>
		/// <returns>Saved category</returns>
		public Category Save(Category category)
		{
			return (Category) HibernateTemplate.Save(category);
		}

		/// <summary>
		/// Saves or updates (if exists) category
		/// </summary>
		/// <param name="category">Category to save</param>
		/// <returns>Saved category</returns>
		public Category SaveOrUpdate(Category category)
		{
			ISession session = SessionFactoryUtils.GetSession(SessionFactory, false);
			session.FlushMode = FlushMode.Auto;
			HibernateTemplate.SaveOrUpdate(category);
			session.Flush();

			return category;
		}

		/// <summary>
		/// Loads all categories
		/// </summary>
		/// <returns>Loaded categories</returns>
		public IList<Category> FindAll()
		{
			return HibernateTemplate.LoadAll<Category>();
		}

		/// <summary>
		/// Loads tree of categories with specified root category
		/// </summary>
		/// <param name="root">Root category of tree data</param>
		/// <returns>Loaded categories</returns>
		public IList<Category> GetTree(Category root)
		{
            if(root == null)
			    return HibernateTemplate.Find<Category>("from Category cat where cat.ParentCategory is null");
            else
                return HibernateTemplate.Find<Category>("from Category cat where cat.ParentCategory = ?", root);
        }

		/// <summary>
		/// Deletes category
		/// </summary>
		/// <param name="category">Category to delete</param>
		public void Detele(Category category)
		{
			ISession session = SessionFactoryUtils.GetSession(SessionFactory, false);
			session.FlushMode = FlushMode.Auto;
			HibernateTemplate.Delete(category);
			session.Flush();
		}

		/// <summary>
		/// Checks if abbreviation is unique
		/// </summary>
		/// <param name="abbreviation">Abbreviation to check</param>
		/// <param name="id">Allowed duplicate abbreviation ID</param>
		/// <returns>Flag if category abbreviation is unique in context</returns>
		public bool IsUnique(string abbreviation, int id)
		{
			return
				HibernateTemplate.Find<Category>("from Category c where c.Abbreviation = ? and c.Id != ?",
				                                 new object[] {abbreviation, id}).Count == 0;
		}

		#endregion
	}
}
